package org.liang.job.impl;

import static org.quartz.JobKey.jobKey;
import static org.quartz.TriggerKey.triggerKey;

import java.util.ArrayList;
import java.util.Set;

import org.liang.job.exceptions.JobException;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 定时任务 控制类.
 * 
 * <pre>
 * 提供对  Scheduler 中 的任务及触发器进行操作的各种行为:
 * 1 触发指定任务
 * 2 暂停指定任务
 * 3 暂停指定组内的任务
 * 4 恢复指定任务
 * 5 恢复指定组内的任务
 * 6 删除指定任务
 * 7 删除指定组内的任务
 * 8 暂停指定触发器
 * 9 暂停指定组内的触发器
 * 10 恢复指定触发器
 * 11 恢复指定组内的触发器
 * 12 移除指定触发器
 * 13 移除指定组内的触发器
 * 
 * </pre>
 * 
 * @author L.Yang
 * @version 1.0, 2015年9月22日
 */
class SchedulerHelper {

    /** 日志对象. */
    private static final Logger LOGGER = LoggerFactory.getLogger(SchedulerHelper.class);

    /**
     * 触发任务.
     * 
     * @param scheduler
     *            计划实例
     * @param jobName
     *            任务名
     * @param jobGroup
     *            任务组
     */
    static void triggerJob(Scheduler scheduler, String jobName, String jobGroup) {
        try {
            scheduler.triggerJob(jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            LOGGER.error("触发定时任务失败", e);
            throw new JobException("触发定时任务失败");
        }
    }

    /**
     * 暂停指定任务.
     * 
     * @param scheduler
     *            计划实例
     * @param jobName
     *            任务名
     * @param jobGroup
     *            任务组
     */
    static void pauseJob(Scheduler scheduler, String jobName, String jobGroup) {
        try {
            scheduler.pauseJob(jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            LOGGER.error("暂停定时任务失败", e);
            throw new JobException("暂停定时任务失败");
        }
    }

    /**
     * 暂停指定组内的任务.
     * 
     * @param scheduler
     *            计划实例
     * @param jobGroup
     *            任务组
     */
    static void pauseJobs(Scheduler scheduler, String jobGroup) {
        try {
            scheduler.pauseJobs(GroupMatcher.jobGroupEquals(jobGroup));
        } catch (SchedulerException e) {
            LOGGER.error("暂停指定组内的任务失败", e);
            throw new JobException("暂停指定组内的任务失败", e);
        }
    }

    /**
     * 恢复指定任务.
     *
     * @param scheduler
     *            计划实例
     * @param jobName
     *            任务名
     * @param jobGroup
     *            任务组
     */
    static void resumeJob(Scheduler scheduler, String jobName, String jobGroup) {
        try {
            scheduler.resumeJob(jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            LOGGER.error("恢复指定任务失败", e);
            throw new JobException("恢复指定任务失败", e);
        }
    }

    /**
     * 恢复指定组内的任务.
     *
     * @param scheduler 计划实例
     * @param jobGroup
     *            任务组
     */
    static void resumeJobs(Scheduler scheduler, String jobGroup) {
        try {
            scheduler.resumeJobs(GroupMatcher.jobGroupEquals(jobGroup));
        } catch (SchedulerException e) {
            LOGGER.error("恢复指定组内的任务失败", e);
            throw new JobException("恢复指定组内的任务失败", e);
        }
    }

    /**
     * 删除定时任务<br>
     * . 同时，相关联的触发器也会被删除
     * 
     * @param scheduler
     *            计划实例
     * @param jobName
     *            任务组
     * @param jobGroup
     *            任务
     */
    static boolean deleteJob(Scheduler scheduler, String jobName, String jobGroup) {
        try {
            return scheduler.deleteJob(jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            LOGGER.error("删除指定任务失败", e);
            throw new JobException("删除指定任务失败", e);
        }
    }

    /**
     * 删除指定组内的任务.<br>
     * 同时，相关联的触发器也会被删除
     * 
     * @param scheduler
     *            计划实例
     * @param jobGroup
     *            任务组
     */
    static boolean deleteJobs(Scheduler scheduler, String jobGroup) {
        try {
            Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupEquals(jobGroup));
            return scheduler.deleteJobs(new ArrayList<JobKey>(jobKeys));
        } catch (SchedulerException e) {
            LOGGER.error("删除指定组内的任务失败", e);
            throw new JobException("删除指定组内的任务失败", e);
        }
    }

    /**
     * 暂停指定触发器.
     * 
     * @param scheduler
     *            计划实例
     * @param triggerName
     *            触发器名
     * @param triggerGroup
     *            触发器组
     */
    static void pauseTrigger(Scheduler scheduler, String triggerName, String triggerGroup) {
        try {
            scheduler.pauseTrigger(triggerKey(triggerName, triggerGroup));
        } catch (SchedulerException e) {
            LOGGER.error("暂停指定触发器失败", e);
            throw new JobException("暂停指定触发器失败", e);
        }
    }

    /**
     * 暂停指定组内的触发器.
     * 
     * @param scheduler 计划实例
     * @param triggerGroup
     *            触发器组
     */
    static void pauseTriggers(Scheduler scheduler, String triggerGroup) {
        try {
            scheduler.pauseTriggers(GroupMatcher.triggerGroupEquals(triggerGroup));
        } catch (SchedulerException e) {
            LOGGER.error("暂停指定组内的触发器失败", e);
            throw new JobException("暂停指定组内的触发器失败", e);
        }
    }

    /**
     * 恢复指定触发器.
     *
     * @param scheduler
     *            计划实例
     * @param triggerName
     *            触发器名
     * @param triggerGroup
     *            触发器组
     */
    static void resumeTrigger(Scheduler scheduler, String triggerName,  String triggerGroup) {
        try {
            scheduler.resumeTrigger(triggerKey(triggerName, triggerGroup));
        } catch (SchedulerException e) {
            LOGGER.error("恢复指定触发器失败", e);
            throw new JobException("恢复指定触发器失败", e);
        }
    }

    /**
     * 恢复指定组内的触发器.
     *
     * @param scheduler
     *            计划实例
     * @param triggerGroup
     *            触发器组
     */
    static void resumeTriggers(Scheduler scheduler, String triggerGroup) {
        try {
            scheduler.resumeTriggers(GroupMatcher.triggerGroupEquals(triggerGroup));
        } catch (SchedulerException e) {
            LOGGER.error("恢复指定组内的触发器失败", e);
            throw new JobException("恢复指定组内的触发器失败", e);
        }
    }

    /**
     * 移除指定触发器.
     *
     * @param scheduler
     *            计划实例
     * @param triggerName
     *            触发器名
     * @param triggerGroup
     *            触发器组
     */
    static boolean removeTrigger(Scheduler scheduler, String triggerName, String triggerGroup) {
        try {
            TriggerKey triggerKey = triggerKey(triggerName, triggerGroup);
            scheduler.pauseTrigger(triggerKey);
            return scheduler.unscheduleJob(triggerKey);// 移除触发器
        } catch (SchedulerException e) {
            LOGGER.error("移除指定触发器失败", e);
            throw new JobException("移除指定触发器失败", e);
        }
    }

    /**
     * 移除指定组内的触发器.
     *
     * @param scheduler
     *            计划实例
     * @param triggerGroup
     *            触发器组
     */
    static boolean removeTriggers(Scheduler scheduler, String triggerGroup) {
        try {
            GroupMatcher<TriggerKey> matcher = GroupMatcher.triggerGroupEquals(triggerGroup);
            scheduler.pauseTriggers(matcher);
            Set<TriggerKey> triggerKeys = scheduler.getTriggerKeys(matcher);
            return scheduler.unscheduleJobs(new ArrayList<TriggerKey>(triggerKeys));// 移除触发器
        } catch (SchedulerException e) {
            LOGGER.error("移除指定组内的触发器失败", e);
            throw new JobException("移除指定组内的触发器失败", e);
        }
    }
}
